#!/usr/bin/env python3
#-*- encoding:utf-8 -*-


"""
文件功能： 跟微信公众号通信的web service
作者: arthur.chen@huawei.com
函数：
  1. @app.route('/wechat',methods=['GET','POST'])   处理来自微信公众号发来的消息
  2. @app.route("/publish", methods=['POST'])   处理向SSE服务端发布的消息
  3. @app.route('/reply', methods=['POST'])  接收并处理即将发往微信公众号的消息 
"""


from flask import Flask, request, make_response
from flask_sse import sse
import logging    #日志
# wechat 公共函数: 校验 signature， 处理消息
from wechat_functions import check_signature, handle_message

# 全局配置
from globals import g_wechat_token, g_appid, g_encode_aes_key, g_queue


# 初始化 Flask
app = Flask(__name__)
app.config['REDIS_URL'] = 'redis://localhost:6379/0'
app.register_blueprint(sse, url_prefix="/stream")

# 初始化日志
logging.basicConfig(filename='/var/log/run.log', 
	format='%(asctime)s - %(levelname)s: %(message)s', 
	level=logging.INFO)
logger = logging.getLogger(__name__)



""" 处理来自微信公众号发来的消息
@param signature: 微信发送消息过来时，url上附带的http请求参数，代表微信公众号签名， 用于验证是否来自微信
@param timestamp: 微信发送消息过来时，url上附带的http请求参数，代表时间戳，用于解密消息
@param nonce: 微信发送消息过来时，url上附带的http请求参数，随机字符串，用于验证验证是否来自微信以及加解密消息
@param echostr: 微信发送消息过来时，url上附带的http请求参数，代表返回字符串，用于验证消息来自微信成功时返回给微信服务器（GET请求）
@param msg_signature:  微信发送消息过来时，url上附带的http请求参数，代表消息签名，用于解密消息
@return: 按照微信公众要要求格式的xml字符串，且进行了加密
"""
@app.route('/wechat',methods=['GET','POST'])
def wechat():	
	# 获取GET请求参数
	token = g_wechat_token
	data = request.args
	signature = data.get('signature', '')
	timestamp = data.get('timestamp', '')
	nonce = data.get('nonce', '')
	echostr = data.get('echostr', '')	
	msg_signature = data.get('msg_signature', '')
	# 验证请求来自微信公众号
	if check_signature(signature, timestamp, nonce, token):  # 成功
		logger.info("check_signature successfully.")	
		if request.method == 'GET':   # GET 请求，返回 echostr
			return make_response(echostr)
		elif request.method == 'POST':  # POST 请求， 处理微信公众号消息
			xml_str = request.data.decode('utf-8')
			res = handle_message(xml_str, nonce, g_appid, g_wechat_token, g_encode_aes_key, msg_signature, timestamp)
			return res
	else:  # 验证失败
		logger.error("Invalid Signature")
		logger.error(f'timestamp:{timestamp}; nonce:{nonce}; signature:{signature}')
		return "Invalid Signature."
	

""" 处理向SSE服务端发布的消息
@param 所有发来的json结构，会原封不动发布到SSE Server端，监听在 /stream 上的sse客户端会收到此消息
@return: 返回204 http code，代表本次请求已经成功处理，但无响应正文
"""
@app.route("/publish", methods=['POST'])
def publish():
	data = request.get_json()
	sse.publish(data, type="message")
	return '', 204


""" 接收并处理即将发往微信公众号的消息
@param 所有发来的json结构，会原封不动发布到SSE Server端，监听在 /stream 上的sse客户端会收到此消息
@return: 
"""
@app.route('/reply', methods=['POST'])
def reply():
	data = request.get_json()
	g_queue.put(data)
	return '', 204


if __name__ == '__main__':
	logger.info('\nServer Started.\n')
	app.run(host='0.0.0.0', port=80, debug=True)
